using Vwf.Tools;

namespace Vwf.Vwt {
	
	public class ParserControl : Parser {
		protected BlockControl myContent { get { return (BlockControl)content; } }
		protected string chIdentifierFirst = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
		protected string chIdentifierNext  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789";

		public override void parse() throws EDParser, EDStrParser {
			myContent.className = getIdentifier();
			if (strParser.followedBy("#")) {
				strParser.rmove(1);
				myContent.controlName = getIdentifier();
			};
			passWhitespace();
			while(true) {
				if (strParser.followedBy("?>")) {
					strParser.rmove(2);
					return;
				}
				if (strParser.eos()) {
					throw new EDParser.UnexpectedEOF("");
				}
				string paramName = getIdentifier();
				passWhitespace();
				if (!strParser.followedBy("=")) {
					throw new EDParser.Expected("Expected char '=' after param name.");
				}
				strParser.rmove(1);
				passWhitespace();
				
				string ch = strParser.charAtCursor();
				if (ch == "(") {
					var parser = (ParserVala)getParser("Vala");
					parser.mode = ParserVala.Mode.Expression;
					parser.parse();
					myContent.addProperty(paramName, parser.myContent.code, BlockVala.Type.Expression);
				} else if (ch == "{") {
					var parser = (ParserVala)getParser("Vala");
					parser.mode = ParserVala.Mode.CodeBlock;
					parser.parse();
					myContent.addProperty(paramName, parser.myContent.code, BlockVala.Type.Delegate);
				} else if ((ch >= "0") && (ch <= "9")) {
					string cStart = strParser.storeCursor();
					strParser.findNextNonChar("0123456789.");
					myContent.addProperty(paramName, strParser.substring(cStart), BlockVala.Type.Expression);
				} else if (((ch >= "A") && (ch <= "Z")) || ((ch >= "a") && (ch <= "z")) || (ch == "_")) {
					myContent.addProperty(paramName, getIdentifier(), BlockVala.Type.Expression);
				} else if (ch == "\"") {
					if (strParser.followedBy("\"\"\"")) {
						string cStart = strParser.storeCursor();
						strParser.rmove(3);
						if (!strParser.findNext("\"\"\"")) throw new EDParser.UnexpectedEOF("Unterminated verbatim string");
						strParser.toEndChunk();
						myContent.addProperty(paramName, strParser.substring(cStart), BlockVala.Type.Expression);
					} else {
						string cStart = strParser.storeCursor();
						strParser.rmove(1);
						do {
							if (!strParser.findAnyNext(new string[] { "\\\"", "\"" })) throw new EDParser.UnexpectedEOF("Unterminated string");
							strParser.toEndChunk();
							// if (strParser.lastChunk == "\n") throw new EDParser.UnexpectedEOF("String");
							
						} while (strParser.lastChunk != "\"");
						strParser.toEndChunk();
						myContent.addProperty(paramName, strParser.substring(cStart), BlockVala.Type.Expression);
					}
				} else {
					throw new EDParser.Unexpected("UnExpected char '" + ch + "' in param content.");
				}
				if (passWhitespace() == 0) throw new EDParser.Expected("Expected whitespace after param content.");
			}
			
			/* 
				var parser = getParser(strParser.substring(cStart));
				strParser.toEndChunk();
				return parser;
			} else {
				throw new EDParser.UnexpectedEOF("");
			};
			do {
				strParser.storeCursor(cStart);
				if (strParser.findAnyNext(new string[] { "?>", "<?" })) {
					add(new BlockHtml(strParser.substring(cStart)));
					strParser.toEndChunk();
					switch (strParser.lastChunk) {
						case "?>":
							logMsg("Konnec bloku ");
							strParser.toEndChunk();
							return;
						case "<?":
							logMsg("zjistuju dalsi parser ");
							var parser = getNextParser();
							parser.Parse();
							add(parser.content);
							break;
					}
				} else {
					logMsg("Konnec textu ");
					break;
				};
			} while (true); */
		}
		public ParserControl() {
			content = new BlockControl();
			blockTypes = new string[] {"c", "control"};
		}
		/* protected void add(Block item) {
			myContent.addProperty(item);
		} */
		protected string getIdentifier() {
			string cStart = strParser.storeCursor();
			// Must begin with a-zA-Z_
			if (strParser.findNextNonChar(chIdentifierFirst) == 0) throw new EDParser.Expected("Expected identifier");
			// Maybe contains a-zA-Z_0-9
			strParser.findNextNonChar(chIdentifierNext);
			
			return strParser.substring(cStart);
		}
	}
}
